package cn.legend.travel.passport.filter;


import cn.legend.travel.common.enumerator.ServiceCode;
import cn.legend.travel.common.pojo.authentication.CurrentPrincipal;
import cn.legend.travel.common.pojo.po.UserStatePO;
import cn.legend.travel.common.web.JsonResult;
import cn.legend.travel.passport.dao.cache.IUserCacheRepository;
import com.alibaba.fastjson.JSON;

import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

@Component
public class JwtAuthorizationFilter extends OncePerRequestFilter {
    @Value("${travel.jwt.secret-key}")
    private String secretKey;

    @Autowired
    private IUserCacheRepository iUserCacheRepository;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String requestURI = request.getRequestURI();
        if (requestURI.endsWith(".css")||requestURI.endsWith(".js")){
            filterChain.doFilter(request,response);
            return;
        }

//        SecurityContextHolder.clearContext();

//        System.out.println(request.getRequestURI());
//        System.out.println("JwtAuthorizationFilter.doFilterInternal()");

        // 尝试接收JWT
        String jwt = request.getHeader("Authorization");
//        System.out.println("客户端携带的JWT：" + jwt);

        if (!StringUtils.hasText(jwt)){
//            System.out.println("jwt过滤器放行");
            filterChain.doFilter(request,response);
            return;
        }

        Claims claims=null;
        response.setContentType("application/json;charset=utf-8");
        try{
            claims = Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(jwt)
                    .getBody();
        }catch (ExpiredJwtException e){
            String message="您的登录信息已经过期！请重新登录!";
            JsonResult jsonResult=JsonResult.fail(ServiceCode.ERROR_UNAUTHORIZED_DISABLED,message);
            PrintWriter printWriter=response.getWriter();
            printWriter.println(JSON.toJSONString(jsonResult));
            printWriter.close();
            return;
        }catch (SignatureException e){
            String message="非法访问！";
            JsonResult jsonResult=JsonResult.fail(ServiceCode.ERR_JWT_SIGNATURE,message);
            PrintWriter printWriter=response.getWriter();
            printWriter.println(JSON.toJSONString(jsonResult));
            printWriter.close();
            return;
        }catch (MalformedJwtException e){
            String message="非法访问！";
            JsonResult jsonResult=JsonResult.fail(ServiceCode.ERR_JWT_MALFORMED,message);
            PrintWriter printWriter=response.getWriter();
            printWriter.println(JSON.toJSONString(jsonResult));
            printWriter.close();
            return;
        }catch (Throwable e){
            String message="服务器繁忙！请稍后再试!";
            JsonResult jsonResult=JsonResult.fail(ServiceCode.ERROR_UNKNOWN,message);

            PrintWriter printWriter=response.getWriter();
            printWriter.println(JSON.toJSONString(jsonResult));
            printWriter.close();
            return;
        }

        Long id = claims.get("id",Long.class);
        String username = claims.get("username",String.class);
        String jwtRemoteAddr=claims.get("remote_addr",String.class);
        String jwtUserAgent=claims.get("user_agent",String.class);

        String remoteAddr=request.getRemoteAddr();
        String userAgent=request.getHeader("User-Agent");

//        System.out.println("jwt地址:"+jwtUserAgent);
//        System.out.println("jwt的ip:"+jwtRemoteAddr);
//        System.out.println("地址："+userAgent);
//        System.out.println("当前ip:"+remoteAddr);

        if (!remoteAddr.equals(jwtRemoteAddr) && !userAgent.equals(jwtUserAgent)){
            filterChain.doFilter(request,response);
            return;
        }

        //更新用户状态信息
        iUserCacheRepository.expire(id);

        CurrentPrincipal principal=new CurrentPrincipal();
        principal.setId(id);
        principal.setUsername(username);


        UserStatePO userStatePO=iUserCacheRepository.getUserState(id);
        //验证是否获取到用户状态信息
        if (userStatePO==null){
            String message="您的登录信息已过期！";
            JsonResult jsonResult=JsonResult.fail(ServiceCode.ERROR_UNAUTHORIZED_DISABLED,message);
//            response.setContentType("application/json;charset=utf-8");
            PrintWriter printWriter=response.getWriter();
            printWriter.println(JSON.toJSONString(jsonResult));
            printWriter.close();
            return;
        }

        List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
        authorityList.add(new SimpleGrantedAuthority("AUTHORITY"));

        Authentication authentication = new UsernamePasswordAuthenticationToken(principal,
                null, authorityList);
        SecurityContext securityContext = SecurityContextHolder.getContext();
        securityContext.setAuthentication(authentication);

        filterChain.doFilter(request,response);


    }
}
